<template>
  <div class="lazy-image-container" :class="{ 'loaded': isLoaded, 'error': hasError }">
    <!-- 骨架屏 -->
    <ImageSkeleton v-if="!isLoaded && !hasError" />
    
    <!-- 图片 -->
    <img
      v-show="isLoaded && !hasError"
      :src="currentSrc"
      :alt="alt"
      :class="imageClass"
      @load="handleImageLoad"
      @error="handleImageError"
      :loading="loading"
    />
    
    <!-- 错误占位图 -->
    <div v-if="hasError" class="error-placeholder">
      <div class="error-icon">📷</div>
      <div class="error-text">图片加载失败</div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, watch } from 'vue'
import ImageSkeleton from './ImageSkeleton.vue'

const props = defineProps({
  src: {
    type: String,
    required: true
  },
  alt: {
    type: String,
    default: '图片'
  },
  loading: {
    type: String,
    default: 'lazy',
    validator: (value) => ['lazy', 'eager'].includes(value)
  },
  imageClass: {
    type: String,
    default: ''
  },
  placeholder: {
    type: String,
    default: '/placeholder-image.jpg'
  },
  threshold: {
    type: Number,
    default: 0.1
  }
})

const emit = defineEmits(['load', 'error'])

const isLoaded = ref(false)
const hasError = ref(false)
const isInView = ref(false)
const observer = ref(null)

// 计算当前显示的图片源
const currentSrc = computed(() => {
  if (hasError.value) {
    return props.placeholder
  }
  return isInView.value ? props.src : ''
})

// 处理图片加载成功
const handleImageLoad = () => {
  isLoaded.value = true
  hasError.value = false
  emit('load')
}

// 处理图片加载失败
const handleImageError = () => {
  hasError.value = true
  isLoaded.value = false
  emit('error')
}

// 设置交叉观察器
const setupIntersectionObserver = () => {
  if (!window.IntersectionObserver) {
    // 降级处理：直接加载图片
    isInView.value = true
    return
  }

  observer.value = new IntersectionObserver(
    (entries) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          isInView.value = true
          observer.value?.unobserve(entry.target)
        }
      })
    },
    {
      threshold: props.threshold,
      rootMargin: '50px'
    }
  )
}

// 监听图片源变化
watch(() => props.src, (newSrc) => {
  if (newSrc && newSrc !== currentSrc.value) {
    isLoaded.value = false
    hasError.value = false
    isInView.value = false
    
    // 重新设置观察器
    if (observer.value) {
      observer.value.disconnect()
      setupIntersectionObserver()
    }
  }
})

onMounted(() => {
  setupIntersectionObserver()
  
  // 开始观察
  const container = document.querySelector('.lazy-image-container')
  if (container && observer.value) {
    observer.value.observe(container)
  }
})
</script>

<style scoped lang="less">
.lazy-image-container {
  width: 100%;
  height: 100%;
  position: relative;
  overflow: hidden;
  border-radius: 12px;
  
  img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: opacity 0.3s ease;
    
    &.loaded {
      opacity: 1;
    }
  }
  
  .error-placeholder {
    width: 100%;
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    background: #f5f5f5;
    color: #999;
    
    .error-icon {
      font-size: 2rem;
      margin-bottom: 8px;
    }
    
    .error-text {
      font-size: 0.9rem;
    }
  }
}
</style> 